package com.bootdo.order.service.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.bootdo.common.utils.PicQrcodeUtil;
import com.bootdo.order.utils.OrderSequence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.bootdo.common.config.Constant;
import com.bootdo.common.configure.dao.DictDao;
import com.bootdo.common.configure.domain.DictDO;
import com.bootdo.common.redis.lock.CommonRedisLock;
import com.bootdo.common.utils.DateUtils;
import com.bootdo.common.utils.StringUtils;
import com.bootdo.merchant.dao.MerchantDao;
import com.bootdo.merchant.domain.MerchantDO;
import com.bootdo.mq.RabbitUtil;
import com.bootdo.mq.SendSortUtil;
import com.bootdo.order.dao.OrderDao;
import com.bootdo.order.dao.OrderPayDao;
import com.bootdo.order.domain.OrderDO;
import com.bootdo.order.domain.OrderPayDO;
import com.bootdo.order.service.OrderService;
import com.bootdo.order.utils.MD5SignUtil;
import com.bootdo.payee.dao.PayeeAgentDao;
import com.bootdo.payee.dao.PayeeDao;
import com.bootdo.payee.dao.PaymentCodeDao;
import com.bootdo.payee.domain.PayeeAgentDO;
import com.bootdo.payee.domain.PayeeDO;
import com.bootdo.payee.domain.PaymentCodeDO;
import com.bootdo.quota.dao.QuotaDao;
import com.bootdo.quota.domain.QuotaDO;
import com.bootdo.rate.dao.RateDao;
import com.bootdo.rate.domain.RateDO;
import com.bootdo.system.dao.UserRoleDao;

/**
 * @author admin
 * @Desc 订单处理
 * @date 2019/11/18
 */
@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private OrderDao orderMapper;
    @Autowired
    private MerchantDao merchantMapper;
    @Autowired
    private PayeeDao payeeMapper;
    @Autowired
    private PaymentCodeDao paymentCodeMapper;
    @Autowired
    private QuotaDao quotaMapper;
    @Autowired
    private RateDao rateMapper;
    @Autowired
    private OrderPayDao orderPayMapper;
    @Autowired
    private PayeeAgentDao payeeAgentMapper;
    @Autowired
    private UserRoleDao userRoleMapper;
    @Autowired
    private DictDao dictMapper;
    @Autowired
    private RabbitUtil rabbitUtil;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private SendSortUtil sendSortUtil;

    @Value("${alipay.returnUrl}")
    private String returnUrl;
    @Value("${bootdo.uploadPath}")
    private String filePath;
    @Value("${bootdo.path}")
    private String urlPath;

    /**
     * 验证必填项
     *
     * @param order
     * @throws Exception
     */
    @Override
    public void check(OrderDO order) throws Exception {
        if (StringUtils.isBlank(order.getIdentification())) {
            throw new Exception("商户编号不能为空");
        }
        if (StringUtils.isBlank(order.getOrderNo())) {
            throw new Exception("订单编号不能为空");
        }
        if (null == order.getPayType()) {
            throw new Exception("支付类型不能为空");
        }
        if (null == order.getMoney()) {
            throw new Exception("支付金额不能为空");
        }
        if (StringUtils.isBlank(order.getSign())) {
            throw new Exception("签名不能为空");
        }
        if (null == order.getRequestTime()) {
            throw new Exception("当前时间戳不能为空");
        }

        long time = System.currentTimeMillis();
        long timeLong = time - order.getRequestTime();
        double timeDouble= Double.parseDouble(Long.toString(timeLong));
        if (timeDouble/(double)1000 > 600){
            throw new Exception("当前请求超时");
        }

    }

    @Override
    public void checkSign(OrderDO order) throws Exception {
        MerchantDO merchant = merchantMapper.getByIdent(order.getIdentification());
        Map<String, String> map = new HashMap<>();
        map.put("token", merchant.getToken());
        map.put("payType", order.getPayType() + "");
        map.put("identification", order.getIdentification());
        map.put("requestTime", String.valueOf(order.getRequestTime()));
        boolean f = MD5SignUtil.verify(map, order.getSign());
        if (!f) {
            throw new Exception("验签失败");
        }
    }

    @Override
    public void checkMerchant(OrderDO order) throws Exception {
        MerchantDO merchant = merchantMapper.getByIdent(order.getIdentification());
        if (merchant == null){
            throw new Exception("当前商户不存在，请联系管理员");
        }
        Double minMoney = merchant.getMinMoney();
        Double minWeiXinMoney = merchant.getMinWeiXinMoney();
        Double minAlipayTransMoney = merchant.getMinAlipayTransMoney();
        if (order.getPayType()==1) {
            if (minMoney == null) {
                throw new Exception("当前商户未设置支付宝固码最小收款金额，请联系管理员");
            }
            if (minMoney > order.getMoney()) {
                throw new Exception("当前订单金额小于商户支付宝固码最小金额");
            }
        } else if (order.getPayType()==2) {
            if (minWeiXinMoney == null) {
                throw new Exception("当前商户未设置微信固码最小收款金额，请联系管理员");
            }
            if (minWeiXinMoney > order.getMoney()) {
                throw new Exception("当前订单金额小于商户微信固码最小金额");
            }
        } else if (order.getPayType()==3) {
            if (minAlipayTransMoney == null) {
                throw new Exception("当前商户未设置支付宝转账最小收款金额，请联系管理员");
            }
            if (minAlipayTransMoney > order.getMoney()) {
                throw new Exception("当前订单金额小于商户支付宝转账最小金额");
            }
        } else if (order.getPayType()==4) {
            if (minAlipayTransMoney == null) {
                throw new Exception("当前商户未设置支付宝账号(吱口令)最小收款金额，请联系管理员");
            }
            if (minAlipayTransMoney > order.getMoney()) {
                throw new Exception("当前订单金额小于商户付宝账号(吱口令)最小金额");
            }
        } else {
            throw new Exception("当前支付通道设置错误。");
        }
        if (merchant.getStatus() == 0) {
            throw new Exception("当前商户未启用，请联系管理员");
        }
        RateDO rate = rateMapper.getRate(merchant.getUserId(), order.getPayType());
        if (rate == null){
            throw new Exception("当前商户未设置费率");
        }
        //检测创建者是否是平台管理员
        int checkUserIsManager = userRoleMapper.checkUserIsManager(merchant.getUserIdCreate());
        if (checkUserIsManager!=1){
            rate = rateMapper.getRate(merchant.getUserIdCreate(), order.getPayType());
            if (rate == null) {
                throw new Exception("当前商户代理未设置费率");
            }
        }
        logger.debug("=======商户订单========>" + order.toString());
        OrderDO orders = new OrderDO();
        orders.setOrderNo(order.getOrderNo());
        orders.setIdentification(order.getIdentification());
        OrderDO orderDO = orderMapper.getByNoAndId(orders);
        if (orderDO != null) {
            throw new Exception("订单重复，请重新下单");
        }
    }

    /**
     * 获取收款户信息
     *
     * @param payType
     * @return
     */
    @Override
    public PaymentCodeDO findQrcode(int payType, double money, String orderId) {
        //取出排队表中排位第一个用户
        Long userId = findSortUserId(payType, money);
        logger.info("========分配的收款户========>" + userId);
        if (userId != null){
            PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(userId);
            logger.info("========分配的收款户二维码========>" + JSONObject.toJSONString(paymentCode));
            if (paymentCode != null){
                return findQrcodeAfter(paymentCode,payType,money,orderId);
            }
        }
        return null;
    }

    private Long findSortUserId(int payType, double money){
        Long userIdOk = null;
        CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
        String userIds = commonRedisLock.lLeftPop(String.valueOf(Constant.PASSAGEWAY + payType));
        if (StringUtils.isBlank(userIds)){
            return null;
        }
        Long userId = Long.valueOf(userIds);
        String queueName = Constant.QUEUE_START + userId;
        JSONObject object = new JSONObject();
        object.put("code",3);
        object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
        object.put("userId", userId);
        object.put("payType",payType);

        //获取当前排队用户信息
        PayeeDO payee = payeeMapper.get(userId);
        if (payee.getLineStatus().intValue() == 0) {
            object.put("msg","当前收款户不存在接单权限，请联系管理员");
            rabbitUtil.sendToQueue(queueName,object.toJSONString());
            //退出排队
            payee.setLineUpStatus(0);
            payeeMapper.update(payee);
            logger.error("==========当前收款户不存在接单权限，请联系管理员==========>" + userId);
        } else {
            RateDO rate = rateMapper.getRate(payee.getUserId(), payType);
            if (rate == null){
                object.put("msg","当前收款户未设置费率，请联系管理员");
                rabbitUtil.sendToQueue(queueName,object.toJSONString());
                //退出排队
                payee.setLineUpStatus(0);
                payeeMapper.update(payee);
                logger.error("==========当前收款户未设置费率，请联系管理员==========>" + userId);
            } else {
                PayeeAgentDO payeeAgent = payeeAgentMapper.get(payee.getUserIdCreate());
                if (payeeAgent == null) {
                    object.put("msg","当前收款户不存在收款代理，请联系管理员");
                    rabbitUtil.sendToQueue(queueName,object.toJSONString());
                    //退出排队
                    payee.setLineUpStatus(0);
                    payeeMapper.update(payee);
                    logger.error("==========当前收款户不存在收款代理，请联系管理员==========>" + userId);
                } else {
                    rate = rateMapper.getRate(payeeAgent.getUserId(), payType);
                    if (rate == null){
                        object.put("msg","当前收款户代理未设置费率，请联系管理员");
                        rabbitUtil.sendToQueue(queueName,object.toJSONString());
                        //退出排队
                        payee.setLineUpStatus(0);
                        payeeMapper.update(payee);
                        logger.error("==========当前收款户代理未设置费率，请联系管理员==========>" + userId);
                    } else {
                        if (payeeAgent.getStatus().intValue() == 0) {
                            object.put("msg","当前收款户代理已被禁用，请联系管理员");
                            rabbitUtil.sendToQueue(queueName,object.toJSONString());
                            //退出排队
                            payee.setLineUpStatus(0);
                            payeeMapper.update(payee);
                            logger.error("==========当前收款户代理已被禁用，请联系管理员==========>" + userId);
                        } else {
                            QuotaDO quota = quotaMapper.get(payeeAgent.getUserId());
                            if (quota.getActualQuota().doubleValue() < money) {
                                object.put("msg","当前收款户代理余额不足，请联系管理员");
                                rabbitUtil.sendToQueue(queueName,object.toJSONString());
                                //退出排队
                                payee.setLineUpStatus(0);
                                payeeMapper.update(payee);
                                logger.error("==========当前收款户代理余额不足，请联系管理员==========>" + userId);
                            } else {
                                //获取未回单数量
                                List<OrderDO> list = orderMapper.getOrderByPayeeForNo(payee.getUserId());
                                quota = quotaMapper.get(payee.getUserId());
                                if (payee.getUncollectedQuantity().intValue() > list.size()) {
                                    if (quota.getActualQuota().doubleValue() >= money) {
                                        PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(payee.getUserId());
                                        if (paymentCode == null){
                                            object.put("msg","当前收款户无可用收款账户，请联系管理员");
                                            rabbitUtil.sendToQueue(queueName,object.toJSONString());
                                            //退出排队
                                            payee.setLineUpStatus(0);
                                            payeeMapper.update(payee);
                                            logger.error("==========当前收款户无可用收款账户，请联系管理员==========>" + userId);
                                        } else {
                                            paymentCodeMapper.updateEmptyCode(paymentCode.getCodeId(), paymentCode.getEmptyNumber() + 1);
                                            userIdOk =  payee.getUserId();
                                        }
                                    } else {
                                        object.put("msg","当前用户额度不足，请联系管理员");
                                        rabbitUtil.sendToQueue(queueName,object.toJSONString());
                                        //退出排队
                                        payee.setLineUpStatus(0);
                                        payeeMapper.update(payee);
                                        logger.error("==========当前用户额度不足，请联系管理员==========>" + userId);
                                    }
                                } else {
                                    //删除二维码
                                    PaymentCodeDO paymentCode = paymentCodeMapper.getCodeByOk(payee.getUserId());
                                    paymentCodeMapper.paymentCodeDelete(paymentCode);
                                    object.put("msg","未回单数量超限，请联系管理员");
                                    rabbitUtil.sendToQueue(queueName,object.toJSONString());
                                    //退出排队
                                    payee.setLineUpStatus(0);
                                    payeeMapper.update(payee);
                                    logger.error("==========未回单数量超限，请联系管理员==========>" + userId);
                                }
                            }
                        }
                    }
                }
            }
        }
        if (userIdOk == null){
            userIdOk = findSortUserId(payType, money);
        }
        return userIdOk;
    }

    private PaymentCodeDO findQrcodeAfter(PaymentCodeDO paymentCode,int payType, double money, String orderId){
        if (paymentCode == null){
            return null;
        }
        QuotaDO quota = quotaMapper.get(paymentCode.getUserIdCreate());
        PayeeDO payee = payeeMapper.get(paymentCode.getUserIdCreate());
        //获取未回单数量
        List<OrderDO> payeeOrders = orderMapper.getOrderByPayeeForNo(payee.getUserId());
        if (0 < (quota.getActualQuota() - money) && payee.getUncollectedQuantity().intValue() > payeeOrders.size()) {
            //当前二维码是否存在三单空单
            PaymentCodeDO paymentCodes = paymentCodeMapper.get(paymentCode.getCodeId());
            DictDO dictDO = new DictDO();
            dictDO.setType("checkNum");
            dictDO.setIsShow(1);
            DictDO dict = dictMapper.getDictByType(dictDO);
            if (dict != null && Integer.parseInt(dict.getValue()) <= (paymentCodes.getEmptyNumber().intValue() -1)){
                //删除二维码
                paymentCodeMapper.paymentCodeDelete(paymentCode);
                String queueName = Constant.QUEUE_START+paymentCode.getUserIdCreate();
                JSONObject object = new JSONObject();
                object.put("code",3);
                object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
                object.put("userId",paymentCode.getUserIdCreate());
                object.put("payType",payType);
                object.put("msg","当前接单二维码存在过多空单,请重新上传接单二维码");
                rabbitUtil.sendToQueue(queueName,object.toJSONString());
                //退出排队
                payee.setLineUpStatus(0);
                payeeMapper.update(payee);
            }else {
                //加入排队
                CommonRedisLock commonRedisLock = new CommonRedisLock(stringRedisTemplate);
                commonRedisLock.lRightPush(Constant.PASSAGEWAY + paymentCode.getPassagewayId(), String.valueOf(payee.getUserId()));
            }
        } else {
            payee.setLineUpStatus(0);
            payeeMapper.update(payee);
            PaymentCodeDO paymentCodes = paymentCodeMapper.get(paymentCode.getCodeId());
            //删除二维码
            paymentCodeMapper.paymentCodeDelete(paymentCodes);
            String queueName = Constant.QUEUE_START+paymentCodes.getUserIdCreate();
            JSONObject object = new JSONObject();
            object.put("code",3);
            object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
            object.put("userId",paymentCodes.getUserIdCreate());
            object.put("payType",payType);
            object.put("msg","未回单数量超限或余额不足");
            object.put("payType",payType);
            rabbitUtil.sendToQueue(queueName,object.toJSONString());
        }

        String queueName = Constant.QUEUE_START+paymentCode.getUserIdCreate();
        JSONObject object = new JSONObject();
        object.put("code",2);
        object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
        object.put("userId",paymentCode.getUserIdCreate());
        object.put("msg","当前接单金额：" + money);
        object.put("data",orderId);
        object.put("payType",payType);
        rabbitUtil.sendToQueue(queueName, object.toJSONString());
        sendSortUtil.sendMsg(payType);

        if (paymentCode.getPassagewayId().intValue() == 2){
            if (paymentCode.getQrCode().indexOf("wxp") > -1){
                paymentCode.setQrCode(paymentCode.getQrCode().substring(0, paymentCode.getQrCode().indexOf("?")));
            }
        }

        return paymentCode;
    }

    /**
     * 创建订单并生成订单佣金列表
     *
     * @param order
     * @return
     */
    @Override
    public OrderDO save(OrderDO order, Long payeeId) throws Exception {
        //获取当前收款户未回款订单
        logger.debug("=======订单信息=======>" + order.toString());
        order.setActualMoney(order.getMoney());
        String orderId = OrderSequence.createOrderSnRandom();
        order.setId(orderId);
        order.setPayeeId(payeeId);
        order.setGmtCreate(new Date());
        order.setCallBackStatus(0);
        logger.debug("==========生成订单表主键=======>" + orderId);
        if (orderMapper.save(order) <= 0) {
            throw new Exception("创建订单失败");
        }
        return order;
    }

    @Override
    public void saveQuota(OrderPayDO orderPay) {
        //扣除收款户额度和收款户代理额度
        PayeeDO payee = payeeMapper.get(orderPay.getPayeeId());
        JSONObject object = new JSONObject();
        object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
        object.put("orderId", orderPay.getOrderId());
        object.put("type", 2);
        object.put("reason", "接单扣除");
        object.put("money", orderPay.getOrderMoney());

        //收款户
        object.put("userId", payee.getUserId());
        rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());
        //扣除收款户代理额度
        QuotaDO quota = quotaMapper.get(payee.getUserIdCreate());
        if (quota != null) {
            object.put("userId", payee.getUserIdCreate());
            rabbitUtil.sendToQueue(Constant.UPDATE_QUOTA, object.toJSONString());
        }
    }

    /**
     * 设置订单分成
     *
     * @param order
     */
    @Override
    public OrderPayDO saveOrderPay(OrderDO order, String qrCode , String qrCodeRealName , String payAccountPassword) {
        //生成订单佣金列表
        OrderPayDO orderPay = new OrderPayDO();
        orderPay.setOrderId(order.getId());
        orderPay.setPayType(order.getPayType());
        //订单金额
        orderPay.setOrderMoney(order.getMoney());
        //实际支付金额
        orderPay.setActualMoney(order.getActualMoney());
        //收款户id
        orderPay.setPayeeId(order.getPayeeId());
        orderPay.setGmtCreate(new Date());
        //商户自定义单号
        orderPay.setOrderNo(order.getOrderNo());
        //收款户二维码
        orderPay.setPayeeCode(qrCode);
        orderPay.setQrCodeRealName(qrCodeRealName);
        orderPay.setPayAccountPassword(payAccountPassword);

        //获取商户信息
        MerchantDO merchant = merchantMapper.getByIdent(order.getIdentification());
        //商户id
        orderPay.setMerchantId(merchant.getUserId());
        orderPay.setMerchantAgentId(merchant.getUserIdCreate());
        //获取收款户信息
        PayeeDO payee = payeeMapper.get(order.getPayeeId());
        orderPay.setPayeeAgentId(payee.getUserIdCreate());
        //获取商户费率
        RateDO rateMerch = rateMapper.getRate(merchant.getUserId(), orderPay.getPayType());
        //获取商户代理费率
        RateDO rateAgentMer = rateMapper.getRate(merchant.getUserIdCreate(), orderPay.getPayType());
        //收款户费率
        RateDO ratePayee = rateMapper.getRate(payee.getUserId(), orderPay.getPayType());
        //收款户代理费率
        RateDO rateAgentPaye = rateMapper.getRate(payee.getUserIdCreate(), orderPay.getPayType());

        //获取平台利润
        double platMoney = 0.0;
        if (1 == order.getPayType().intValue()) {
            //支付宝固码
            platMoney = order.getMoney() * (rateMerch.getAlipayFixedRate() / 100);
            //订单总费率
            orderPay.setCountMoney(order.getMoney() * (rateMerch.getAlipayFixedRate() / 100));
            if (rateAgentMer != null) {
                platMoney = platMoney - order.getMoney() * ((rateMerch.getAlipayFixedRate() - rateAgentMer.getAlipayFixedRate()) / 100);
                //存在的商户代理手续费
                orderPay.setMerchantMoney(order.getMoney() * ((rateMerch.getAlipayFixedRate() - rateAgentMer.getAlipayFixedRate()) / 100));
            }
            double payeeMoney = order.getMoney() * (ratePayee.getAlipayFixedRate() / 100);
            platMoney = platMoney - payeeMoney;
            //收款户手续费
            orderPay.setPayeeMoney(payeeMoney);
            //收款户应上缴金额
            orderPay.setPayeeTurn(order.getMoney() - payeeMoney);
            if (rateAgentPaye != null) {
                double payeeAgentMoney = order.getMoney() * ((rateAgentPaye.getAlipayFixedRate() - ratePayee.getAlipayFixedRate()) / 100);
                platMoney = platMoney - payeeAgentMoney;
                //存在的收款代理手续费
                orderPay.setPayeeAgentMoney(payeeAgentMoney);
                orderPay.setPayeeAgentTurn(order.getMoney() - payeeMoney - payeeAgentMoney);
            }
        } else if (2 == order.getPayType()) {
            //微信固码
            platMoney = order.getMoney() * (rateMerch.getWeixinFixedRate() / 100);
            //订单总费率
            orderPay.setCountMoney(order.getMoney() * (rateMerch.getWeixinFixedRate() / 100));
            if (rateAgentMer != null) {
                platMoney = platMoney - order.getMoney() * ((rateMerch.getWeixinFixedRate() - rateAgentMer.getWeixinFixedRate()) / 100);
                //存在的商户代理手续费
                orderPay.setMerchantMoney(order.getMoney() * ((rateMerch.getWeixinFixedRate() - rateAgentMer.getWeixinFixedRate()) / 100));
            }
            double payeeMoney = order.getMoney() * (ratePayee.getWeixinFixedRate() / 100);
            platMoney = platMoney - payeeMoney;
            //收款户手续费
            orderPay.setPayeeMoney(payeeMoney);
            //收款户应上缴金额
            orderPay.setPayeeTurn(order.getMoney() - payeeMoney);
            if (rateAgentPaye != null) {
                double payeeAgentMoney = order.getMoney() * ((rateAgentPaye.getWeixinFixedRate() - ratePayee.getWeixinFixedRate()) / 100);
                platMoney = platMoney - payeeAgentMoney;
                //存在的收款代理手续费
                orderPay.setPayeeAgentMoney(payeeAgentMoney);
                orderPay.setPayeeAgentTurn(order.getMoney() - payeeMoney - payeeAgentMoney);
            }
        } else if (3 == order.getPayType()) {
            platMoney = order.getMoney() * (rateMerch.getAlipayTransferRate() / 100);
            //订单总费率
            orderPay.setCountMoney(order.getMoney() * (rateMerch.getAlipayTransferRate() / 100));
            if (rateAgentMer != null) {
                platMoney = platMoney - order.getMoney() * ((rateMerch.getAlipayTransferRate() - rateAgentMer.getAlipayTransferRate()) / 100);
                //存在的商户代理手续费
                orderPay.setMerchantMoney(order.getMoney() * ((rateMerch.getAlipayTransferRate() - rateAgentMer.getAlipayTransferRate()) / 100));
            }
            double payeeMoney = order.getMoney() * (ratePayee.getAlipayTransferRate() / 100);
            platMoney = platMoney - payeeMoney;
            //收款户手续费
            orderPay.setPayeeMoney(payeeMoney);
            //收款户应上缴金额
            orderPay.setPayeeTurn(order.getMoney() - payeeMoney);
            if (rateAgentPaye != null) {
                double payeeAgentMoney = order.getMoney() * ((rateAgentPaye.getAlipayTransferRate() - ratePayee.getAlipayTransferRate()) / 100);
                platMoney = platMoney - payeeAgentMoney;
                //存在的收款代理手续费
                orderPay.setPayeeAgentMoney(payeeAgentMoney);
                orderPay.setPayeeAgentTurn(order.getMoney() - payeeMoney - payeeAgentMoney);
            }
        } else if (4 == order.getPayType()) {
            platMoney = order.getMoney() * (rateMerch.getAlipayAccountTransRate() / 100);
            //订单总费率
            orderPay.setCountMoney(order.getMoney() * (rateMerch.getAlipayAccountTransRate() / 100));
            if (rateAgentMer != null) {
                platMoney = platMoney - order.getMoney() * ((rateMerch.getAlipayAccountTransRate() - rateAgentMer.getAlipayAccountTransRate()) / 100);
                //存在的商户代理手续费
                orderPay.setMerchantMoney(order.getMoney() * ((rateMerch.getAlipayAccountTransRate() - rateAgentMer.getAlipayAccountTransRate()) / 100));
            }
            double payeeMoney = order.getMoney() * (ratePayee.getAlipayAccountTransRate() / 100);
            platMoney = platMoney - payeeMoney;
            //收款户手续费
            orderPay.setPayeeMoney(payeeMoney);
            //收款户应上缴金额
            orderPay.setPayeeTurn(order.getMoney() - payeeMoney);
            if (rateAgentPaye != null) {
                double payeeAgentMoney = order.getMoney() * ((rateAgentPaye.getAlipayAccountTransRate() - ratePayee.getAlipayAccountTransRate()) / 100);
                platMoney = platMoney - payeeAgentMoney;
                //存在的收款代理手续费
                orderPay.setPayeeAgentMoney(payeeAgentMoney);
                orderPay.setPayeeAgentTurn(order.getMoney() - payeeMoney - payeeAgentMoney);
            }
        }
        orderPay.setPlatformMoney(platMoney);
        orderPayMapper.save(orderPay);
        return orderPay;
    }

    /**
     * 拼接返回数据
     *
     * @param order
     * @return
     */
    @Override
    public Map<String, Object> retMerc(OrderDO order, PaymentCodeDO paymentCode) {
        MerchantDO merchant = merchantMapper.getByIdent(order.getIdentification());
        Map<String, String> map = new HashMap<>();
        //支付类型
        map.put("payType", order.getPayType() + "");
        //实际支付金额
        map.put("actualMoney", order.getActualMoney() + "");
        //订单金额
        map.put("money", order.getMoney() + "");
        //平台订单号
        map.put("billNo", order.getId() + "");
        //商户自定义订单号
        map.put("orderNo", order.getOrderNo());
        //商户唯一码
        map.put("identification", order.getIdentification());
        //商户唯一码
        map.put("token", merchant.getToken());
        map.put("requestTime", System.currentTimeMillis() + "");
        map.put("sign", MD5SignUtil.sign(map));

        Map<String, Object> maps = new HashMap<>();
        maps.putAll(map);
        maps.remove("token");
        //收款二维码或支付宝用户id
        maps.put("qCode", paymentCode.getQrCode());
        String qrCodeRealName="";
        String payAccountPassword="";
        if (paymentCode.getPassagewayId()==1) {
            qrCodeRealName = paymentCode.getQrCodeRealName();
            payAccountPassword = paymentCode.getPayAccountPassword();
        }
        //支付宝二维码真实姓名
        maps.put("qrCodeRealName", qrCodeRealName);
        //支付宝口令
        maps.put("payAccountPassword", payAccountPassword);

        //此链接后面跟上订单主键
        maps.put("returnUrl", returnUrl + order.getId());
        return maps;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public Map<String, Object> retMercs(OrderDO order) throws Exception {
        Map<String, Object> map;
        long startTime = System.currentTimeMillis();
        //检验必填项
        check(order);
        long endTime = System.currentTimeMillis();
        logger.debug("第一次程序运行时间：" + (endTime - startTime) + "ms");
        //检验签名
        checkSign(order);
        endTime = System.currentTimeMillis();
        logger.debug("第二次程序运行时间：" + (endTime - startTime) + "ms");
        //校验商户
        checkMerchant(order);
        endTime = System.currentTimeMillis();
        logger.debug("第三次程序运行时间：" + (endTime - startTime) + "ms");
        //获取二维码信息
        PaymentCodeDO paymentCode = findQrcode(order.getPayType(), order.getMoney(), order.getOrderNo());
        endTime = System.currentTimeMillis();
        logger.debug("第四次程序运行时间：" + (endTime - startTime) + "ms");
        if (paymentCode != null) {
            //生成订单信息
            order = save(order, paymentCode.getUserIdCreate());
            endTime = System.currentTimeMillis();
            logger.debug("第五次程序运行时间：" + (endTime - startTime) + "ms");
            //生成佣金信息
            String qrCodeRealName = "";
            String payAccountPassword = "";
            if (paymentCode.getPassagewayId()==1) {
                qrCodeRealName = paymentCode.getQrCodeRealName();
                payAccountPassword = paymentCode.getPayAccountPassword();
            }
            OrderPayDO orderPay = saveOrderPay(order, paymentCode.getQrCode() , qrCodeRealName , payAccountPassword);
            endTime = System.currentTimeMillis();
            logger.debug("第六次程序运行时间：" + (endTime - startTime) + "ms");
            //扣除或增加对应额度
            saveQuota(orderPay);
            endTime = System.currentTimeMillis();
            logger.debug("第七次程序运行时间：" + (endTime - startTime) + "ms");
            map = retMerc(order, paymentCode);
        } else {
            map = null;
        }
        return map;
    }

    @Override
    public void sendMsg(Map<String, Object> map){
        String payType = (String) map.get("payType");
        if (StringUtils.isNotBlank(payType)){
            JSONObject object = new JSONObject();
            object.put("date", DateUtils.format(new Date(),DateUtils.DATE_TIME_PATTERN));
            object.put("payType", payType);
            rabbitUtil.sendToQueue(Constant.CHANG_SORT, object.toJSONString());
        }
    }

    @Override
    public Map<String, String> queryOrder(OrderDO orders) throws Exception {
        //获取订单信息
        if (StringUtils.isBlank(orders.getId())){
            throw new Exception("未传入平台订单号");
        }
        OrderDO order = orderMapper.getByNoAndId(orders);
        if (order == null) {
            throw new Exception("订单异常");
        }
        Map<String, String> map = new HashMap<>();
        //支付类型
        map.put("payType", order.getPayType() + "");
        //实际支付金额
        map.put("actualMoney", order.getActualMoney() + "");
        //订单金额
        map.put("money", order.getMoney() + "");
        //平台订单号
        map.put("billNo", order.getId() + "");
        //商户自定义订单号
        map.put("orderNo", order.getOrderNo());
        //订单状态
        map.put("type", order.getType() + "");
        Calendar cal = Calendar.getInstance();
        cal.setTime(order.getGmtCreate());
        //设置超时时间600秒
        map.put("orderTime", cal.getTimeInMillis()/1000 + "");

        //获取订单信息
        OrderPayDO orderPay = orderPayMapper.getByOrderId(order.getId());
        map.put("code", orderPay.getPayeeCode());
        String qrCodeRealName="";
        String payAccountPassword="";
        if(1 == orderPay.getPayType()){
            qrCodeRealName = orderPay.getQrCodeRealName();
            payAccountPassword = orderPay.getPayAccountPassword();
            qrCodeRealName = StringUtils.overlay(qrCodeRealName, "***", 1, qrCodeRealName.length());
        }
        //支付宝二维码真实姓名
        map.put("qrCodeRealName", qrCodeRealName);
        //支付宝口令
        map.put("payAccountPassword", payAccountPassword);
        return map;
    }

    @Override
    public Map<String, String> queryRet(OrderDO orders) throws Exception {
        if (StringUtils.isBlank(orders.getId())){
            throw new Exception("未传入平台订单号");
        }
        if (StringUtils.isBlank(orders.getOrderNo())){
            throw new Exception("未传入商户订单号");
        }
        //获取订单信息
        OrderDO order = orderMapper.getByNoAndId(orders);
        if (order == null) {
            throw new Exception("订单异常");
        }
        MerchantDO merchant = merchantMapper.getByIdent(order.getIdentification());

        Map<String, String> map = new HashMap<>();
        //支付类型
        map.put("payType", order.getPayType() + "");
        //实际支付金额
        map.put("actualMoney", order.getActualMoney() + "");
        //订单金额
        map.put("money", order.getMoney() + "");
        //平台订单号
        map.put("billNo", order.getId());
        //商户自定义订单号
        map.put("orderNo", order.getOrderNo());
        //订单状态
        map.put("type", order.getType() + "");
        map.put("identification", order.getIdentification());
        map.put("requestTime", System.currentTimeMillis() + "");
        map.put("token", merchant.getToken());
        map.put("sign", MD5SignUtil.sign(map));

        return map;
    }

    @Override
    public List<MerchantDO> findMerchant(){
        List<MerchantDO> list =  merchantMapper.list(new HashMap<>());
        return list;
    }

    @Override
    public OrderDO createOrderParam(OrderDO order) throws Exception{
        MerchantDO merchant = merchantMapper.getByIdent(order.getIdentification());
        Map<String, String> map = new HashMap<>();
        long requestTime = System.currentTimeMillis();
        map.put("requestTime", requestTime + "");
        map.put("token", merchant.getToken());
        map.put("identification", merchant.getIdentification());
        map.put("payType", order.getPayType() + "");
        order.setSign(MD5SignUtil.sign(map));
        order.setRequestTime(requestTime);
        return order;
    }

}
